package org.javaforever.cookieshop.serviceimpl;

import java.util.List;
import java.util.Set;
import java.util.TreeSet;
import org.javaforever.cookieshop.dao.PermissionDao;
import org.javaforever.cookieshop.dao.RoleDao;
import org.javaforever.cookieshop.domain.PermissionBean;
import org.javaforever.cookieshop.domain.RoleBean;
import org.javaforever.cookieshop.service.PermissionService;
import org.javaforever.cookieshop.service.RoleService;
import org.javaforever.cookieshop.utils.StringUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import jakarta.persistence.EntityManager;
import jakarta.persistence.PersistenceContext;
import jakarta.persistence.Query;

@Service
public class RoleServiceImpl implements RoleService{
	@Autowired
	protected RoleDao dao;

	@Autowired
	protected PermissionDao permissionDao;

	@Autowired
	protected PermissionService permissionService;
	@PersistenceContext
	protected EntityManager entityManager;

	@Override
	public void activateAllRoles(String ids) throws Exception{
        String [] idArr = ids.split(",");
        for (String idString : idArr){
            Long id = Long.valueOf(idString);
            dao.activateRole(id);
        }
	}

	@Override
	public Boolean activateRole(Long id) throws Exception{
        dao.activateRole(id);
        return true;
	}

	@Override
	@Transactional
	public Boolean addRole(RoleBean role) throws Exception{
        dao.saveAndFlush(role);
        return true;
	}

	@Override
	@Transactional
	public Boolean assignPermissionsToRole(Long roleId,String permissionIds) throws Exception{
        String [] permissionIdsArr = permissionIds.split(",");
        for (int i = 0; i < permissionIdsArr.length; i++ ){
        Long permissionId = Long.parseLong(permissionIdsArr[i]);
        Integer success = dao.assignPermissionToRole(roleId,permissionId);
        if (success < 0) return false;
        }
        return true;
	}

	@Override
	public void cloneAllRoles(String ids) throws Exception{
        String [] idArr = ids.split(",");
        for (String idString : idArr){
            Long id = Long.valueOf(idString);
            cloneRole(id);
        }
	}

	@Override
	public Boolean cloneRole(Long id) throws Exception{
        RoleBean role = dao.findRoleFullInfoById(id);
        
        String roleName = role.getRoleName();
        String shortName = roleName;
        if (roleName.contains("_") && StringUtil.isInteger(roleName.substring(roleName.lastIndexOf('_')+1,roleName.length()))) {
            shortName = roleName.substring(0,roleName.lastIndexOf('_'));
        }
        List<RoleBean> names = dao.searchRoleIndexedNamesByShortName(shortName);
        int indexNum = 1;
        for (RoleBean role0:names) {
            String _name = role0.getRoleName();
            if (_name.contains("_") && StringUtil.isInteger(_name.substring(_name.lastIndexOf('_')+1,_name.length()))) {
                int index = Integer.valueOf(_name.substring(_name.lastIndexOf('_')+1,_name.length()));
                if (index >= indexNum) {
                    indexNum = index + 1;
                }
            }
        }
        String indexName = shortName + "_" + indexNum;
        RoleBean role1 = role.clone();
        role1.setId(null);
        role1.setRoleName(indexName);
        addRole(role1);
        return true;
	}

	@Override
	public Integer countActiveRoleRecords() throws Exception{
        return dao.countActiveRoleRecords();
	}

	@Override
	public Integer countSearchRolesByFieldsRecords(RoleBean role) throws Exception{
        String jpql = "select count(*) as countNum from RoleBean r where 1=1 ";
        if (role.getRoleName() != null) {
            jpql += " and r.roleName like CONCAT('%', '"+role.getRoleName()+"','%')";
        }
        if (role.getActive() != null) {
            jpql += " and r.active = "+role.getActive();
        }
        Query query = entityManager.createQuery(jpql);
        Long count = (Long) query.getSingleResult();
        return count.intValue();
	}

	@Override
	public void deleteAllRoles(String ids) throws Exception{
        String [] idArr = ids.split(",");
        for (String idString : idArr){
            Long id = Long.valueOf(idString);
            dao.deleteRole(id);
        }
	}

	@Override
	public Boolean deleteRole(Long id) throws Exception{
        dao.deleteRole(id);
        return true;
	}

	@Override
	public RoleBean findRoleById(Long id) throws Exception{
        return dao.findRoleById(id);
	}

	@Override
	public RoleBean findRoleByRoleName(String roleName) throws Exception{
        return dao.findRoleByRoleName(roleName);
	}

	@Override
	public Set<PermissionBean> listActiveRolePermissionsUsingRoleId(Long roleId) throws Exception{
        Set<PermissionBean> _set = new TreeSet<PermissionBean>();
        _set.addAll(permissionDao.listActiveRolePermissionsUsingRoleId(roleId));
        return _set;
	}

	@Override
	public List<RoleBean> listActiveRoles() throws Exception{
        return dao.listActiveRoles();
	}

	@Override
	public List<RoleBean> listAllRoles() throws Exception{
        return dao.listAllRoles();
	}

	@Override
	public Set<PermissionBean> listAvailableActiveRolePermissionsUsingRoleId(Long roleId) throws Exception{
        Set<PermissionBean> fullset = new TreeSet<PermissionBean>();
        fullset.addAll(permissionService.listActivePermissions());
        Set<PermissionBean> set = listActiveRolePermissionsUsingRoleId(roleId);
        fullset.removeAll(set);	
        return fullset;
	}

	@Override
	@Transactional
	public Boolean revokePermissionsFromRole(Long roleId,String permissionIds) throws Exception{
        String [] permissionIdsArr = permissionIds.split(",");
        for (int i = 0; i < permissionIdsArr.length; i++ ){
        Long permissionId = Long.parseLong(permissionIdsArr[i]);
        Integer success = dao.revokePermissionFromRole(roleId,permissionId);
        if (success < 0) return false;
        }
        return true;
	}

	@Override
	public List<RoleBean> searchRolesByFields(RoleBean role) throws Exception{
        String jpql = "from RoleBean r where 1=1 ";
        if (role.getRoleName() != null) {
            jpql += " and r.roleName like CONCAT('%', '"+role.getRoleName()+"','%')";
        }
        if (role.getActive() != null) {
            jpql += " and r.active = "+role.getActive();
        }
        Query query = entityManager.createQuery(jpql);
        List<RoleBean> results = query.getResultList();
        return results;
	}

	@Override
	public List<RoleBean> searchRolesByFieldsByPage(RoleBean role,Integer pagesize,Integer pagenum) throws Exception{
        Integer start = (pagenum-1)*pagesize;
        Integer limit = pagesize;
        String jpql = "from RoleBean r where 1=1 ";
        if (role.getRoleName() != null) {
            jpql += " and r.roleName like CONCAT('%', '"+role.getRoleName()+"','%')";
        }
        if (role.getActive() != null) {
            jpql += " and r.active = "+role.getActive();
        }
        Query query = entityManager.createQuery(jpql);
        query.setFirstResult(start); // 设置起始位置
        query.setMaxResults(limit); // 设置返回结果数量
        List<RoleBean> results = query.getResultList();
        return results;
	}

	public void setDao(RoleDao dao){
		this.dao = dao;
	}

	public void setPermissionService(PermissionService permissionService){
		this.permissionService = permissionService;
	}

	@Override
	public void softDeleteAllRoles(String ids) throws Exception{
        String [] idArr = ids.split(",");
        for (String idString : idArr){
            Long id = Long.valueOf(idString);
            dao.softDeleteRole(id);
        }
	}

	@Override
	public boolean softDeleteRole(Long id) throws Exception{
        dao.softDeleteRole(id);
        return true;
	}

	@Override
	public Boolean toggleOneRole(Long id) throws Exception{
        RoleBean role = dao.findRoleById(id);
        if (role.getActive()==false) {
            dao.toggleRole(id);
        }
        else {
            Integer count = dao.countActiveRoleRecords();
            if (count > 1){
                dao.toggleRole(id);
            }
        }
        return true;
	}

	@Override
	public Boolean toggleRole(Long id) throws Exception{
        dao.toggleRole(id);
        return true;
	}

	@Override
	@Transactional
	public Boolean updateRole(RoleBean role) throws Exception{
        entityManager.merge(role);
        return true;
	}

}
